local filename = "roomcmd.lua"

local skynet = require "skynet"
local cluster = require "skynet.cluster"
require "skynet.manager"

local servicepoolmng = require "incrservicepoolmng"
local configdao = require "configdao"
local timetool = require "timetool"
local filelog = require "filelog"
local robotscheduler = require("pszscheduler")
require "pszenum"

local CMD = {}
local table_service_map = {}
local index_to_code = {}
local table_list = {publist = {}, mylist = {}}
local robotsnum = {pub = {}, mine = {}, match = {}, coinmatch = {}}
local router
local service = {
	idx = 1,
}
local rolestats = {}
local counter = {
	zijian_diamond = 0,
	match_diamond = 0,
	zijian_coin = 0,
	match_coin = 0,
	zijian_fangka = 0,
}
local matchcounter = {0,0,0,0}	-- 各个匹配场人数统计

-- 生成一个桌子号，随机码
local function gen_table_code(table_index, create_rid, table_conf)
	local newcode = cluster.call("hallnode", ".router", "create_table_code", skynet.getenv("nodename"), table_index, create_rid, table_conf)
	return newcode
end

function CMD.init_table_pool(nodeconf)
	service.idle_table_mng = servicepoolmng:new({}, {service_name = "table", service_size = nodeconf.tablesize, incr=nodeconf.tableinrc})
end

function CMD.update_table_player(idx, data)
	if data.is_public and data.is_public == 1 then
		table_list.publist[idx].cur_player = data.cur_player
		table_list.publist[idx].logo = table_list.publist[idx].logo or {}
		table_list.publist[idx].logo[data.rid] = data.logo
	else
		-- table_list.mylist[idx].cur_player = data.cur_player
		local mtype = data.mtype
		if mtype then
			if data.rtype == ERoomType.ROOM_TYPE_DIAMOND then
				router.update_match_fulltable(idx, data.cur_player, mtype)
				matchcounter[mtype] = (matchcounter[mtype] or 0) + data.count
			-- elseif data.rtype == ERoomType.ROOM_TYPE_COIN then
			-- 	router.update_coinmatch_fulltable(idx, data.cur_player, mtype)
			end
		end
	end
end

function CMD.change_robot_num(num, idx, is_public, match_type, room_type)
	if is_public and is_public == 1 then
		robotsnum.pub[idx] = (robotsnum.pub[idx] or 0) + num
	else
		robotsnum.mine[idx] = (robotsnum.mine[idx] or 0) + num
	end
	if match_type then
		if room_type == ERoomType.ROOM_TYPE_DIAMOND then
			robotsnum.match[match_type] = (robotsnum.match[match_type] or 0) + num
		elseif room_type == ERoomType.ROOM_TYPE_COIN then
			robotsnum.coinmatch[match_type] = (robotsnum.coinmatch[match_type] or 0) + num
		end
	end
end

function CMD.get_tables_data(gtype)
	local tablemap = {}
	for i, v in pairs(table_service_map) do
		if v.conf.game_room_type == gtype then
			tablemap[i] = v
		end
	end
	return tablemap
end

function CMD.get_tables_codes()
	return index_to_code
end

function CMD.getpubtablelist(rid, roledata)
	local list = {publist = {}, mylist = {}}
	local i = 1
	for idx, data in pairs(table_list.publist) do
		list.publist[i] = {
			table_index	= data.table_index,
			table_code	= data.table_code,
			dizhu 		= data.base_score,
			ruchang		= data.enter_diamond,
			lichang		= data.leave_diamond,
			conf_intro	= data.conf_intro,
			max_player	= data.max_player,
			cur_player	= data.cur_player,
			create_time	= data.create_time,
		}
		i = i + 1
		if i > 30 then
			break
		end
	end
	--获得匹配场信息
    list.matchlist = router.get_matchlist()
	return list
end

function CMD.getcoinmatchlist(rid, roledata)
    local list = {publist = {}, mylist = {}}
	local i = 1
	for idx, data in pairs(table_list.publist) do
		list.publist[i] = {
			table_index	= data.table_index,
			table_code	= data.table_code,
			dizhu 		= data.base_score,
			ruchang		= data.enter_diamond,
			lichang		= data.leave_diamond,
			conf_intro	= data.conf_intro,
			max_player	= data.max_player,
			cur_player	= data.cur_player,
			create_time	= data.create_time,
		}
		i = i + 1
		if i > 30 then
			break
		end
	end
	--获得匹配场信息
    list.matchlist = router.get_coinmatchlist()
	return list
end

local function get_alltableplayers()
	local n = 0
	for _, v in pairs(table_service_map) do
		if v.conf.game_room_type == EGameRoomType.ROOM_TYPE_ZIJIAN_ZUANSI then
			n = n + (skynet.call(v.table_service, "lua", "gettableplayer",  rid, rdata, args) or 0)
		end
	end
	return n
end

function CMD.getgamestate()
    local result = {
        zijian_fangka = counter.zijian_fangka,
        zijian_diamond = counter.zijian_diamond,	-- get_alltableplayers(),
        zijian_coin = counter.zijian_coin,
        match_diamond = counter.match_diamond,
        match_coin = counter.match_coin,
    }
	result.match_diamond = result.match_diamond + router.get_matching_player()
	-- result.match_coin = result.match_coin + router.get_matching_player_coin()
	-- ("getgamestate:", counter, result)
	return result
end

function CMD.get_matchroom_count()
	local result = {}
	for k, v in pairs(matchcounter) do
		result[k] = {}
		result[k].match_type = k
		result[k].total_player = v + router.get_matching_player(k)
	end
	return result
end

--[[游戏房间类型
EGameRoomType = {
    ROOM_TYPE_ZIJIAN_FANGKA = 1,        --自建房卡房
    ROOM_TYPE_ZIJIAN_ZUANSI = 2,        --自建钻石房
    ROOM_TYPE_MATCH_ZUANSHI = 3,        --匹配钻石房
    ROOM_TYPE_MATCH_COIN = 4,           --匹配金豆房
    ROOM_TYPE_ZIJIAN_COIN = 5,          --自建金豆房
}
--]]
local function player_counter(gtype, num)
	if gtype == 1 then
		counter.zijian_fangka = counter.zijian_fangka + num
	elseif gtype == 2 then
		counter.zijian_diamond = counter.zijian_diamond + num
	elseif gtype == 3 then
		counter.match_diamond = counter.match_diamond + num
	elseif gtype == 4 then
		counter.match_coin = counter.match_coin + num
	elseif gtype == 5 then
		counter.zijian_coin = counter.zijian_coin + num
	end
end

function CMD.createtable(rid, rdata, args)
	-- filelog.debug("createtable ======>>>", args)
	local responsemsg = {}
	if router.will_kill then
		responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
		responsemsg.retstr = "服务器维护中"
		return responsemsg
	end
	if rolestats[rid] then
		filelog.sys_error("CMD.createfriendtable creating!")
		return
	end
	rolestats[rid] = 1
	local role_data = router.get_role_data(rid)
	if role_data then
		rolestats[rid] = nil
		return
	end
	local card_cost_type = 1
	local create_cost = 0
	args.config.table_type = args.config.table_type or ERoomType.ROOM_TYPE_DIAMOND
	local money = rdata.money
	if args.config.table_type == ERoomType.ROOM_TYPE_ZJ_FRIEND then
		args.config.is_public = 0
		args.config.retain_to_num = args.config.retain_to_num or 8
		create_cost = 4
		if args.config.retain_to_num == 4 then
			create_cost = 2
		end
		if card_cost_type == 1 then
			-- if rdata.money.fangka < create_cost then
			if rdata.money.coin < create_cost*100 then
				responsemsg.retcode = EErrCode.ERR_NOTENOUGH_COIN
				responsemsg.retstr = "金币数量不够！"
				filelog.sys_error("CMD.createfriendtable lack of fangka 1")
				rolestats[rid] = nil
				return responsemsg
			end
		else
			-- if rdata.money.fangka < create_cost/3 then
			if rdata.money.fangka < 100*create_cost/3 then
				responsemsg.retcode = EErrCode.ERR_NOTENOUGH_COIN
				responsemsg.retstr = "金币数量不够！"
				filelog.sys_error("CMD.createfriendtable lack of fangka 2")
				rolestats[rid] = nil
				return responsemsg
			end
		end
	elseif args.config.table_type == ERoomType.ROOM_TYPE_DIAMOND then
		if not money or not money.diamond then
			responsemsg.retcode = EErrCode.ERR_NOT_ENOUGH_DIAMOND
			responsemsg.retstr = "您的余额不足，请前往充值！"
			filelog.sys_error("CMD.creatediamondtable lack of diamond 1")
			rolestats[rid] = nil
			return responsemsg
		end
		if money.diamond < (args.config.enter_diamond or 1000) then
			responsemsg.retcode = EErrCode.ERR_NOT_ENOUGH_DIAMOND
			responsemsg.retstr = "您的余额不足，请前往充值！"
			filelog.sys_error("CMD.creatediamondtable lack of diamond 2")
			rolestats[rid] = nil
			return responsemsg
		end
	elseif args.config.table_type == ERoomType.ROOM_TYPE_COIN then
		if not money or not money.coin then
			-- responsemsg.retcode = EErrCode.ERR_NOT_ENOUGH_COIN
			responsemsg.retcode = EErrCode.ERR_NOT_ENOUGH_DIAMOND
			responsemsg.retstr = "您的金币不足，请前往充值！"
			filelog.sys_error("CMD.createcointable lack of coin 1")
			rolestats[rid] = nil
			return responsemsg
		end
		if (money.coin < 10) or (money.coin + money.diamond < (args.config.enter_diamond or 1000)) then
			-- responsemsg.retcode = EErrCode.ERR_NOT_ENOUGH_COIN
			responsemsg.retcode = EErrCode.ERR_NOT_ENOUGH_DIAMOND
			responsemsg.retstr = "您的金币不足，请前往充值！"
			filelog.sys_error("CMD.createcointable lack of coin 2")
			rolestats[rid] = nil
			return responsemsg
		end
	elseif args.config.table_type == ERoomType.ROOM_TYPE_ZJ_DIAMOND then
		args.config.is_public = 0
		args.config.retain_to_num = args.config.retain_to_num or 10
		create_cost = args.config.retain_to_num
		if not money or not money.diamond then
			responsemsg.retcode = EErrCode.ERR_NOT_ENOUGH_DIAMOND
			responsemsg.retstr = "您的余额不足，请前往充值！"
			filelog.sys_error("CMD.createzjdiamondtable lack of diamond 1")
			rolestats[rid] = nil
			return responsemsg
		end
		if money.diamond < (args.config.enter_diamond or 1000) then
			responsemsg.retcode = EErrCode.ERR_NOT_ENOUGH_DIAMOND
			responsemsg.retstr = "您的余额不足，请前往充值！"
			filelog.sys_error("CMD.createzjdiamondtable lack of diamond 2")
			rolestats[rid] = nil
			return responsemsg
		end
		if money.diamond < create_cost * 100 then
			responsemsg.retcode = EErrCode.ERR_NOT_ENOUGH_DIAMOND
			responsemsg.retstr = "您的余额不足，请前往充值！"
			filelog.sys_error("CMD.createzjdiamondtable lack of diamond 3")
			rolestats[rid] = nil
			return responsemsg
		end
		if (args.config.base_diamond or args.config.base_score) > (args.config.enter_diamond or 0) then
			responsemsg.retcode = EErrCode.ERR_INVALID_PARAMS
			responsemsg.retstr = "参数错误！"
			filelog.sys_error("CMD.createzjdiamondtable: 参数错误！")
			rolestats[rid] = nil
			return responsemsg
		end
	end

	local conf = {
		room_type = args.config.table_type or ERoomType.ROOM_TYPE_DIAMOND,
		game_room_type = args.config.game_room_type or EGameRoomType.ROOM_TYPE_ZIJIAN_ZUANSI,
		name = rdata.info.rolename .. "的房间",
		game_type = args.config.mode or args.config.game_type or EGameType.GAME_TYPE_COMMON,
		is_public = args.config.is_public or 1,
	    max_player_num = 5,	--最大玩家数
		min_player_num = 2,	-- 最少玩家数
	    create_user_rid = rid,
	    create_user_name = rdata.info.rolename,
	    create_user_logo = rdata.info.logo,
	    create_time = timetool.get_time(),
	   	action_timeout = 20,	--玩家出牌时间
		base_score = args.config.base_diamond or args.config.base_score or 100,
		max_score = args.config.max_diamond or args.config.max_score or 2000,
		min_carry_diamond = args.config.enter_diamond or 200,
		leave_carry_diamond = args.config.leave_diamond or 200,
		rid = rid,
		force_overturns = 20,
		create_cost = create_cost,
		retain_time = rdata.table_persist or 10,	-- 桌子保留时间
		game_times = args.config.retain_to_num or 0,
		ready_timeout = 20,
		match_type = args.config.match_type
	}

	if conf.room_type == ERoomType.ROOM_TYPE_ZJ_FRIEND then
		conf.retain_time = 10
		conf.base_score = 1
		conf.game_room_type = EGameRoomType.ROOM_TYPE_ZIJIAN_FANGKA
	elseif conf.room_type == ERoomType.ROOM_TYPE_COIN then
		if not conf.game_room_type then
			conf.game_room_type = EGameRoomType.ROOM_TYPE_ZIJIAN_COIN
		end
	end

	local tableservice = service.idle_table_mng:create_service()
	local table_code, table_service, idx
	local nowtime = timetool.get_time()
	if tableservice ~= nil then
		--生成随机码
		table_service = tableservice.service
		idx = service.idx
		table_code = gen_table_code(idx, rid, args.config)

		conf.table_code = table_code
		conf.create_time = nowtime
		conf.idx = idx

		local result, msg = skynet.call(table_service, "lua", "start", conf)
		if not result then
			pcall(skynet.kill, table_service)
			responsemsg.retcode = EErrCode.ERR_SYSTEM_ERROR
			responsemsg.retstr = "系统错误，创建房间失败！"
			filelog.sys_error("CMD.createfriendtable failed!")
			rolestats[rid] = nil
			return responsemsg
		end
		if conf.is_public and conf.is_public == 1 then
			table_list.publist[idx] = {
				table_type		= conf.room_type,
				table_index		= idx,
				table_code		= table_code,
				base_score 		= conf.base_score,
				enter_diamond	= conf.min_carry_diamond,
				leave_diamond	= conf.leave_carry_diamond,
				conf_intro		= {game_type = conf.game_type},
				max_player		= conf.max_player_num,
				cur_player		= 0,
				create_time		= conf.create_time,
				game_type		= conf.game_type,
			}
		end
		service.idx = service.idx + 1
	else
		filelog.sys_error("CMD:createtable roomsvr's idle_table_mng has no enough tableservice!")
		responsemsg.retcode = EErrCode.ERR_SYSTEM_ERROR
		responsemsg.retstr = "系统错误，创建房间失败！"
		rolestats[rid] = nil
		return responsemsg
	end

	responsemsg.table_index = idx
	table_service_map[table_code] = {
		table_index = idx,
		table_service = table_service,
		create_rid = rid,
		conf = conf,
		create_time = conf.create_time,
	}
	index_to_code[idx] = table_code

	--[[
	-- 自建桌扣费
	if args.config.table_type == ERoomType.ROOM_TYPE_ZJ_DIAMOND then
		-- game_sub_fangfei
		local val = create_cost * 100
		local values = {}
		values[rid] = {
			beginvalue = money.diamond,
			value = val,
			endvalue = money.diamond - val,
		}
		local commnet = {
			table_uuid = skynet.getenv("nodename") .. "_" .. table_code .. "_" .. idx .. "_" .. nowtime,		
			table_tradeid = skynet.call(".nodeuuid", "lua", "getuuid"),
			start_time = nowtime,
		}
		pcall(cluster.call, "gatenode", ".router", "game_sub_fangfei", values, commnet)
	end
	--]]

	rolestats[rid] = nil
    return responsemsg
end

function CMD.entertable(rid, rdata, args)
	-- filelog.debug("entertable ======>>>", args)
	local responsemsg = {}
	if router.will_kill then
		responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
		responsemsg.retstr = "服务器维护中"
		return responsemsg
	end

	if rolestats[rid] then
		-- filelog.sys_error("CMD.entertable entering!")
		return
	end
	rolestats[rid] = 1
	local role_data = router.get_role_data(rid)
	if role_data then
		-- filelog.sys_error("CMD.entertable: 玩家进桌状态异常！")
		rolestats[rid] = nil
		return
	end

	if not rdata.info.is_test and cluster.call("gatenode", ".router", "check_role_state", rid, 0) then
		responsemsg.retcode = EErrCode.ERR_HAD_IN_TABLE
		responsemsg.retstr = "已经在游戏中了！"
		return responsemsg
	end

	local code = index_to_code[args.table_index]
	if not code or not table_service_map[code] then
		responsemsg.retcode = EErrCode.ERR_INVALID_PARAMS
		responsemsg.retstr = "没有找到桌子！"
		filelog.sys_error("CMD.entertable: 没有找到桌子！")
		rolestats[rid] = nil
		return responsemsg
	else
		local game_room_type = table_service_map[code].conf.game_room_type
		-- if (router.check_is_matchtable(args.table_index) or router.check_is_coinmatchtable(args.table_index))
		if router.check_is_matchtable(args.table_index)
		and not args.match_type
		and args.match_type ~= table_service_map[code].conf.match_type then
			responsemsg.retcode = EErrCode.ERR_INVALID_PARAMS
			responsemsg.retstr = "没有找到桌子！"
			filelog.sys_error("CMD.entertable match: 没有找到桌子！")
			rolestats[rid] = nil
			return responsemsg
		end

		local table_service = table_service_map[code].table_service
		local table_index = table_service_map[code].table_index
		args = args or {}
		args.rid = rid
		args.playerinfo = rdata.info
		args.money = rdata.money
		local ok, result = pcall(skynet.call, table_service, "lua", "entertable", args)
		if ok then
			responsemsg = result
			if not result.retcode or result.retcode == 0 then
				router.forward(rid, table_service, table_index)
				if rdata.info.level ~= 99 then
					player_counter(game_room_type, 1)
				end
			end
		else
			responsemsg.retcode = EErrCode.ERR_INVALID_PARAMS
			responsemsg.retstr = "没有找到桌子！"
			filelog.sys_error("CMD.entertable: 没有找到桌子！", result)
			return responsemsg
		end
	end
	rolestats[rid] = nil
	return responsemsg
end

function CMD.reentertable(rid, rdata, args)
	local responsemsg = {
		-- retcode = EErrCode.ERR_SUCCESS,
	}
	local role_data = router.get_role_data(rid)
	if not role_data or not role_data.tablesvr then
		responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
		responsemsg.retstr = "没有找到桌子！"
		filelog.sys_error("CMD.reentertable: 没有找到桌子！")
		router.unforward(rid, args.table_index)
	else
		local table_service = role_data.tablesvr
		args = args or {}
		args.rid = rid
		args.playerinfo = rdata.info
		args.money = rdata.money
		local ok, result = pcall(skynet.call, table_service, "lua", "reentertable", args)
		if not ok then
			responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
			responsemsg.retstr = "没有找到桌子！"
			filelog.sys_error("CMD.reentertable: 没有找到桌子！", result)
		else
			responsemsg = result
		end
		if responsemsg then
			if responsemsg.retcode and responsemsg.retcode ~= 0 then
				router.unforward(rid, args.table_index)
			else
				router.forward(rid, table_service, role_data.idx)
			end
		end
	end
	return responsemsg
end

function CMD.rid_change_diamond(rid, begindiamond, value, enddiamond)
	local role_data = router.get_role_data(rid)
	if not role_data or not role_data.tablesvr then
		responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
		responsemsg.retstr = "玩家没在游戏中！"
		filelog.sys_error("CMD.reentertable: 玩家没在游戏中！")
	else
		local table_service = role_data.tablesvr
		skynet.send(table_service, "lua", "rid_change_diamond", rid, begindiamond, value, enddiamond)
	end
end

function CMD.rid_change_coin(rid, begindiamond, value, enddiamond)
	local role_data = router.get_role_data(rid)
	if not role_data or not role_data.tablesvr then
		responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
		responsemsg.retstr = "玩家没在游戏中！"
		filelog.sys_error("CMD.reentertable: 玩家没在游戏中！")
	else
		local table_service = role_data.tablesvr
		skynet.send(table_service, "lua", "rid_change_coin", rid, begindiamond, value, enddiamond)
	end
end

function CMD.get_tableinfo(table_index, rid)
	local roledata = router.get_role_data(rid)
	if not roledata then return end
	local table_code = index_to_code[table_index]
	if not table_code then return end
	return table_service_map[table_code]
end

function CMD.get_alltableinfo()
	local responsemsg = {
		match_infos = {},
	}

	local match_lists, waiting_robot, waiting_player, unfull_table_nums = router.get_matchlist(true)
	for index, list in pairs(match_lists) do
		responsemsg.match_infos[list.match_type] = {
			cur_total_player = list.cur_total_player,
			cur_robot_num = robotsnum.match[list.match_type] or 0,
			enter_score = list.conf_intro.enter_diamond,
			base_score = list.conf_intro.base_diamond,
			game_type = list.conf_intro.game_type,
			waiting_player = waiting_player[list.match_type] or 0,
			waiting_robot = waiting_robot[list.match_type] or 0,
			unfull_table_num = unfull_table_nums[list.match_type],
		}
	end
	-- filelog.debug("get_alltableinfo:", responsemsg)
	return responsemsg
end

function CMD.delete(table_code)
	local idx
	if table_service_map[table_code] then
		local table_service = table_service_map[table_code].table_service
		idx = table_service_map[table_code].table_index
		table_service_map[table_code] = nil
		index_to_code[idx] = nil
		if router.clear_full_matchtable then
			router.clear_full_matchtable(idx)
		end
		skynet.send(table_service, "lua", "exit_service")
		cluster.send("hallnode", ".router", "del_table_code", table_code, skynet.getenv("nodename"), idx)
	end
	if idx then
		table_list.publist[idx] = nil
		table_list.mylist[idx] = nil
	end
end

function CMD.destroytable(table_code, table_index)
	if table_service_map[table_code] then
		local table_service = table_service_map[table_code].table_service
		skynet.send(table_service, "lua", "leaveallplayers")
	end
end

function CMD.playerleavetable(rid, game_room_type, isrobot)
	if rid then
		router.unforward(rid)
		if not isrobot then	-- 没有统计机器人
			player_counter(game_room_type, -1)
		end
	end
end

function CMD.set_gameend_flag()
	router.will_kill = true
	for k, v in pairs(table_service_map) do
		skynet.send(v.table_service, "lua", "kill")
	end
	router.robot_gameend()
end

function CMD.set_tableend_flag(code)
	return true
end

function CMD.clear_player_state(rid)
	router.unforward(rid)
end

function CMD.addjackoptnum(childid, moneydata, reason)
	local status, result = skynet.pcall(skynet.call, ".jackpotmgr", "lua", "addjackoptnum", childid, moneydata, reason)
	if not status then
		return false
	end
	return result
end

function CMD.deljackoptnum(childid, moneydata, reason)
	local status, result = skynet.pcall(skynet.call, ".jackpotmgr", "lua", "deljackoptnum", childid, moneydata, reason)
	if not status then
		return false
	end
	return result
end

function CMD.getsysperinfo(chargename)
	local status, result = skynet.pcall(skynet.call, ".jackpotmgr", "lua", "getsysperinfo", chargename)
	if not status then
		return nil
	end
	return result
end

function CMD.changesysper(chargename, percent)
	local status, result = skynet.pcall(skynet.call, ".jackpotmgr", "lua", "changesysper", chargename, percent)
	if not status then
		return nil
	end
	return result
end

-- function CMD.get_robot_stat()
-- 	return robotscheduler.get_robot_stat()
-- end

function CMD.change_schedule_state(newstat)
	robotscheduler.change_schedule_state(newstat)
end

local robotmgr = require "robotmgr"
function CMD.init(base)
	router = base
	-- robotscheduler.init(base)
	-- robotscheduler.change_schedule_state(true)

	robotmgr.start(base)
	robotmgr.set_game_robot_state(true)
end

return CMD